<?php
/**
 * File iErrorHandler.php
 *
 * This file is part of Royal project
 *
 * PHP versions 5
 *
 * @copyright Copyright (c) 2010, iLogos
 */

  /**
   * iErrorHandler
   *
   * The iErrorHandler class defined error handler
   *
   * @copyright Copyright (c) 2010, iLogos
   */
  class iErrorHandler extends ErrorException {

  /**
   * show error message in browser
   * @var boolean
   * @access private
   */
  private $_show_message_in_browser;

  /**
   * send error message in email
   * @var boolean
   * @access private
   */
  private $_send_to_email;

  /**
   * _startHandler
   *
   * This function initializes error handler
   *
   * @param boolean $send_to_email - send error message to email
   * @param boolean $show_error_messages - show error message in browser
   *
   * @access public
   */
  public function startHandler($send_to_email = true, $show_error_messages = true) {

    $this->_show_message_in_browser = $show_error_messages;
    $this->_send_to_email = $send_to_email;

    ob_start(array($this, '_iObHandler'));
    set_error_handler(array($this, "_iErrorHandler"), 2147483647);
  }

  /**
   * _saveReport
   *
   * This function save data of error in file error.log
   *
   * @param string $text - text of error
   * @param object $e - object of class exception
   *
   * @access private
   */
  private function _saveReport($text, $e, $isFatal = false) {

    $errorTime = microtime_float();

    // save in log
    //iLog::add(($text . "\n" . $e->getTraceAsString()), 'error', null, $errorTime, $isFatal);

    //send email
    if ($this->_send_to_email === true && defined('ERROR_REPORTING_EMAIL_ADDRESS')) {
      error_log($text . "\n" . $e->getTraceAsString()."\n", 1, ERROR_REPORTING_EMAIL_ADDRESS);
    }

    //save in folder error
    $file_error  = fopen(DIR_VAR_ERROR . 'error_' . $errorTime . '.log', "w");
    fwrite($file_error, date('[D M d H:i:s Y]')." ".($text . "\n" . $e->getTraceAsString())."\n");
    fclose($file_error);
  }

  /**
   * _iObHandler
   *
   * This function handles the error text
   *
   * @param string $text - text of error
   *
   * @return text of error if field _show_message_in_browser = true
   *
   * @access public
   */
  public function _iObHandler($text) {
    $prefix = ini_get('error_prepend_string');
    $suffix = ini_get('error_append_string');
    $re = '{^(.*)(' .
        preg_quote($prefix, '{}') .
        "<br />\r?\n<b>(\w+ error)</b>: \s*" .
        '(.*?)' .
        ' in <b>)(.*?)(</b>' .
        ' on line <b>)(\d+)(</b><br />' .
        "\r?\n" .
        preg_quote($suffix, '{}') .
        ')()$' .
    '}s';

    $p = null;
    if (!preg_match($re, $text, $p)) {
      return $text;
    }

    list (, $content, $beforeFile, $error, $msg, $file, $beforeLine, $line, $afterLine, $tail) = $p;

    try {
      throw new ErrorException($msg);
    } catch(Exception $e) {
      $message = '<b>' . $error . '</b>: ' . $msg . ' in <b>' . $file . '</b>  on line <b>' . $line . '</b>' ;
      $this->_saveReport($message, $e, true);

      if ($this->_show_message_in_browser === true) {
        return $message;
      } else {
        return "error";
      }
    }
  }

  /**
   * _iErrorHandler
   *
   * This function handles the error text
   *
   * @param int $errno - contains the level of the error raised.
   * @param string $errstr - contains the error message.
   * @param string $errfile -  which contains the filename that the error was raised in.
   * @param int $errline -  which contains the line number the error was raised at.
   *
   * @access public
   */
  public function _iErrorHandler($errno, $errstr, $errfile, $errline, $errcontext) {

    try {
      throw new iErrorHandler($errstr, 0, $errno, $errfile, $errline);
    } catch(Exception $e) {
      $text = "Error $errno: $errstr on $errfile line $errline \n";
      $func_args = func_get_args();

      $classes = iFactory::getClasses(false);
      $errfile = str_replace('\\', '/', $errfile);
      $class_name = array_search($errfile, $classes);
      if ($class_name === false) {
        $class_name = '';
      }

      //ALL Database error Detect as Error
      if ( (strpos($class_name, 'database_') !== false) ||
           (preg_match('/.*database_.*/i', $errfile) !== false) ) {
        $errno = E_ERROR;
      }

      /*
       * Swith error by error types
       */
      switch ($errno) {
        /* Fatal run-time errors.
         * These indicate errors that can not be recovered from, such as a memory allocation problem.
         * Execution of the script is halted.
         */
        case E_ERROR:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_ERROR', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;
        /* Run-time warnings (non-fatal errors).
         * Execution of the script is not halted.
         */
        case E_WARNING:
          $continue_code = iControl::ThreatProcessor(CET_WARNING, 'E_WARNING', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Compile-time parse errors.
         * Parse errors should only be generated by the parser.
         */
        case E_PARSE:
          $continue_code =iControl::ThreatProcessor(CET_ERROR, 'E_PARSE', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Run-time notices.
         * Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script.
         */
        case E_NOTICE:
          $continue_code =iControl::ThreatProcessor(CET_WARNING, 'E_NOTICE', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Fatal errors that occur during PHP's initial startup.
         * This is like an E_ERROR, except it is generated by the core of PHP.
         */
        case E_CORE_ERROR:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_CORE_ERROR', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Warnings (non-fatal errors) that occur during PHP's initial startup.
         * This is like an E_WARNING, except it is generated by the core of PHP.
         */
        case E_CORE_WARNING:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_CORE_WARNING', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Fatal compile-time errors.
         * This is like an E_ERROR, except it is generated by the Zend Scripting Engine.
         */
        case E_COMPILE_ERROR:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_COMPILE_ERROR', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Compile-time warnings (non-fatal errors).
         * This is like an E_WARNING, except it is generated by the Zend Scripting Engine.
         */
        case E_COMPILE_WARNING:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_COMPILE_WARNING', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* User-generated error message.
         * This is like an E_ERROR, except it is generated in PHP code by
         * using the PHP function trigger_error().
         */
        case E_USER_ERROR:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_USER_ERROR', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* User-generated warning message.
         * This is like an E_WARNING, except it is generated in PHP code by
         * using the PHP function trigger_error().
         */
        case E_USER_WARNING:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_USER_WARNING', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* User-generated notice message.
         * This is like an E_NOTICE, except it is generated in PHP code by
         * using the PHP function trigger_error().
         */
        case E_USER_NOTICE:
          $continue_code = iControl::ThreatProcessor(CET_WARNING, 'E_USER_NOTICE', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Enable to have PHP suggest changes to your code which will ensure the
         * best interoperability and forward compatibility of your code.
         */
        case E_STRICT:
          $continue_code = iControl::ThreatProcessor(CET_WARNING, 'E_STRICT', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Catchable fatal error. It indicates that a probably dangerous
         * error occured, but did not leave the Engine in an unstable state.
         * If the error is not caught by a user defined handle (see also
         * set_error_handler()), the application aborts as it was an E_ERROR.
         */
        case E_RECOVERABLE_ERROR:
          $continue_code = iControl::ThreatProcessor(CET_ERROR, 'E_RECOVERABLE_ERROR', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* Run-time notices. Enable this to receive warnings about code that
         * will not work in future versions.
         */
        case E_DEPRECATED:
          $continue_code = iControl::ThreatProcessor(CET_WARNING, 'E_DEPRECATED', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

        /* User-generated warning message. This is like an E_DEPRECATED, except it
         * is generated in PHP code by using the PHP function trigger_error().
         */
        case E_USER_DEPRECATED:
          $continue_code = iControl::ThreatProcessor(CET_WARNING, 'E_USER_DEPRECATED', $errfile, $class_name, '', $errline, $errstr, serialize($func_args));
        break;

      }

      $this->_saveReport($text, $e);
      if ($this->_show_message_in_browser === true) {
        echo "<pre>" . $text . $e->getTraceAsString() . "</pre>";
      }

      if (!$continue_code) {
        exit ;
      }
    }

  }
}

?>